From df46d3520618c41dae22794a93ada7abfe20ed95 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 13 Feb 2008 16:35:51 +0000 Subject: [PATCH] vmx realmode: __hvm_copy() should not hvm_get_segment_register() when we are emulating. Firstly it is bogus, since VMCS segment state is stale in this context. Secondly, real mode and real->protected contexts are rather unlikely tohappen with SS.DPL == 3. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/hvm.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index e2e94a9c5f..92a63bf325 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -1386,6 +1386,7 @@ void hvm_task_switch( static enum hvm_copy_result __hvm_copy( void *buf, paddr_t addr, int size, int dir, int virt, int fetch) { + struct vcpu *curr = current; unsigned long gfn, mfn; p2m_type_t p2mt; char *p; @@ -1394,12 +1395,22 @@ static enum hvm_copy_result __hvm_copy( if ( virt ) { - struct segment_register sreg; - hvm_get_segment_register(current, x86_seg_ss, &sreg); - if ( sreg.attr.fields.dpl == 3 ) - pfec |= PFEC_user_mode; + /* + * We cannot use hvm_get_segment_register() while executing in + * vmx_realmode() as segment register state is cached. Furthermore, + * VMREADs on every data access hurts emulation performance. + */ + if ( !curr->arch.hvm_vmx.vmxemul ) + { + struct segment_register sreg; + hvm_get_segment_register(curr, x86_seg_ss, &sreg); + if ( sreg.attr.fields.dpl == 3 ) + pfec |= PFEC_user_mode; + } + if ( dir ) pfec |= PFEC_write_access; + if ( fetch ) pfec |= PFEC_insn_fetch; } @@ -1411,7 +1422,7 @@ static enum hvm_copy_result __hvm_copy( if ( virt ) { - gfn = paging_gva_to_gfn(current, addr, &pfec); + gfn = paging_gva_to_gfn(curr, addr, &pfec); if ( gfn == INVALID_GFN ) { if ( virt == 2 ) /* 2 means generate a fault */ @@ -1435,7 +1446,7 @@ static enum hvm_copy_result __hvm_copy( if ( dir ) { memcpy(p, buf, count); /* dir == TRUE: *to* guest */ - paging_mark_dirty(current->domain, mfn); + paging_mark_dirty(curr->domain, mfn); } else memcpy(buf, p, count); /* dir == FALSE: *from guest */ -- 2.30.2